﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

internal class PostProcessWiiPlayer
{
    private static bool isDevelopmentBuild;
    private static string moduleExtension;
    private static string moduleName;
    private static string moduleNameExt;
    private static string wiiBuildTools;

    internal static bool CopyAndModifyUnityFile(string srcPath, string dstPath, string productName, string variantName)
    {
        PlayerData data;
        byte[] bytes = File.ReadAllBytes(srcPath);
        string str = Encoding.ASCII.GetString(bytes);
        if (ReplaceString(bytes, str.IndexOf("YOUR_PRODUCT_NAME_HERE"), productName, 0x20) == -1)
        {
            UnityEngine.Debug.LogError("Failed to find 'YOUR_PRODUCT_NAME_HERE'");
            return false;
        }
        string replace = string.Format("UnityWii-{0} r{1}", variantName, InternalEditorUtility.GetUnityRevision());
        if (ReplaceString(bytes, str.IndexOf("WII_PLAYER_BUILD_TAG_HERE678901"), replace, 0x20) == -1)
        {
            UnityEngine.Debug.LogError("Failed to find 'WII_PLAYER_BUILD_TAG_HERE678901'");
            return false;
        }
        int index = str.IndexOf("WII_PLAYER_DATA12345");
        if (index == -1)
        {
            UnityEngine.Debug.LogError("Failed to find 'WII_PLAYER_DATA12345'");
            return false;
        }
        data = new PlayerData {
            region = (byte) PlayerSettings.Wii.region,
            hbmConfirmMessage = 0,
            movieMemKB = 0x4d2,
            mixed = 0,
            mixed = (byte) (data.mixed | (!PlayerSettings.Wii.supportsNunchuk ? ((byte) 0) : ((byte) 1))),
            mixed = (byte) (data.mixed | ((byte) (((PlayerSettings.Wii.supportsClassicController == null) ? 0 : 1) << 1))),
            mixed = (byte) (data.mixed | ((byte) (((PlayerSettings.Wii.supportsBalanceBoard == null) ? 0 : 1) << 2))),
            mixed = (byte) (data.mixed | ((byte) (((PlayerSettings.Wii.supportsMotionPlus == null) ? 0 : 1) << 3))),
            mixed = (byte) (data.mixed | 0),
            mixed = (byte) (data.mixed | ((byte) (((PlayerSettings.Wii.floatingPointExceptions == null) ? 0 : 1) << 5))),
            mixed = (byte) (data.mixed | ((byte) (((PlayerSettings.Wii.screenCrashDumps == null) ? 0 : 1) << 6))),
            controllerCount = (byte) PlayerSettings.Wii.controllerCount
        };
        Array values = Enum.GetValues(typeof(WiiMemoryLabel));
        if (values.Length > 0x80)
        {
            UnityEngine.Debug.LogError("WiiMemoryLabel has too many items: " + values.Length);
            return false;
        }
        data.memorySetup0 = 0;
        data.memorySetup1 = 0;
        data.memorySetup2 = 0;
        data.memorySetup3 = 0;
        for (int i = 0; i < values.Length; i++)
        {
            int num6 = i / 0x20;
            int num7 = i % 0x20;
            int num8 = (PlayerSettings.Wii.GetMemoryArea((WiiMemoryLabel) i) != WiiMemoryArea.One) ? 1 : 0;
            switch (num6)
            {
                case 0:
                    data.memorySetup0 |= num8 << num7;
                    break;

                case 1:
                    data.memorySetup1 |= num8 << num7;
                    break;

                case 2:
                    data.memorySetup2 |= num8 << num7;
                    break;

                case 3:
                    data.memorySetup3 |= num8 << num7;
                    break;
            }
        }
        if (Application.platform == RuntimePlatform.WindowsEditor)
        {
            data.movieMemKB = SwapInt32(data.movieMemKB);
            data.memorySetup0 = SwapInt32(data.memorySetup0);
            data.memorySetup1 = SwapInt32(data.memorySetup1);
            data.memorySetup2 = SwapInt32(data.memorySetup2);
            data.memorySetup3 = SwapInt32(data.memorySetup3);
        }
        IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(data));
        Marshal.StructureToPtr(data, ptr, true);
        if (Marshal.SizeOf(data) > 0x20)
        {
            UnityEngine.Debug.LogError("PlayerData is too big: " + Marshal.SizeOf(data));
            Marshal.FreeHGlobal(ptr);
            return false;
        }
        Marshal.Copy(ptr, bytes, index, Marshal.SizeOf(data));
        Marshal.FreeHGlobal(ptr);
        File.WriteAllBytes(dstPath, bytes);
        return true;
    }

    internal static void CreateDirectoryStructure(string installPath)
    {
        FileUtil.DeleteFileOrDirectory(installPath + "/Package");
        if (IsDVDBuild() && isDevelopmentBuild)
        {
            FileUtil.DeleteFileOrDirectory(installPath + "/CWAutomation");
        }
        if (!Directory.Exists(installPath))
        {
            Directory.CreateDirectory(installPath);
        }
        Directory.CreateDirectory(installPath + "/Package");
        if (IsDVDBuild())
        {
            Directory.CreateDirectory(installPath + "/Package/WiiPlayer");
            if (isDevelopmentBuild)
            {
                Directory.CreateDirectory(installPath + "/CWAutomation");
            }
        }
        else
        {
            Directory.CreateDirectory(installPath + "/Package/WiiWarePlayer");
        }
        if (IsLibraryBuild())
        {
            FileUtil.DeleteFileOrDirectory(installPath + "/Source/Libs");
            Directory.CreateDirectory(installPath + "/Source");
        }
    }

    private static string FormatDdfEntry(int fileIndex, string filepath)
    {
        string[] textArray1 = new string[] { fileIndex.ToString(), "=\"", filepath, "\",", -fileIndex.ToString() };
        return string.Concat(textArray1);
    }

    private static string GenerateDdfContent(string dvdDataFolder, string productName, string moduleName)
    {
        string str = (((((((((string.Empty + "[Input]\n") + "DvdRoot=\"$(UNITY_WII_PROJECT)\"\n" + "LDRFileName=\"$(REVOLUTION_SDK_ROOT)/RVL/boot/apploader.img\"\n") + "BI2FileName=\"$(REVOLUTION_SDK_ROOT)/x86/bin/bi2.bin\"\n" + "RVLSysFileName=\"$(REVOLUTION_SDK_ROOT)/x86/bin/rvl.bin\"\n") + "BootFileName=\"$(UNITY_WII_PROJECT)/WiiPlayer/" + moduleName + ".dol\"\n") + "\n" + "[Output]\n") + "LayoutFileName=\"$(UNITY_WII_PROJECT)/WiiPlayer/" + moduleName + ".dlf\"\n") + "SystemFileName=\"$(UNITY_WII_PROJECT)/WiiPlayer/" + moduleName + ".dsf\"\n") + "FsInfoFileName=\"$(UNITY_WII_PROJECT)/WiiPlayer/" + moduleName + ".dif\"\n") + "ConfigFileName=\"$(UNITY_WII_PROJECT)/WiiPlayer/" + moduleName + ".rcf\"\n") + "\n";
        str = (((((((str + "[DiskID]\n") + "GameName=" + PlayerSettings.Wii.gameCode + "\n") + "Company=" + PlayerSettings.Wii.companyCode + "\n") + "DiskNumber=" + "0" + "\n") + "GameVersion=" + "0" + "\n") + "DiskInfo=\"" + productName + "\"\n") + "TotalDisk=" + "1" + "\n") + "\n";
        str = ((((((((str + "[BB2]\n") + "FSTMaxLength=" + "0" + "\n") + "FSTEndAddress=" + "0x80400000" + "\n") + "FSTuserEnd=" + "0x100000000" + "\n") + "\n") + "[LbaAlign]\n" + "1=\"*.adp\",0x8000\n") + "1=\"*.wav\",0x8000\n" + "1=\"*.pcm\",0x8000\n") + "1=\"*.dat\",0x8000\n" + "1=\"*.hvqm\",0x8000\n") + "\n" + "[Layout]\n";
        int fileIndex = 1;
        foreach (string str8 in Directory.GetFiles(dvdDataFolder, "*", SearchOption.AllDirectories))
        {
            if (!str8.EndsWith("-log.txt"))
            {
                string filepath = str8.Replace('\\', '/');
                str = str + FormatDdfEntry(fileIndex, "Data/" + MakeRelative(filepath, dvdDataFolder)) + "\n";
                fileIndex++;
            }
        }
        return (str + "\n");
    }

    internal static string GetOSVersionFromFile(string file, string libraryDefinition)
    {
        byte[] buffer;
        try
        {
            buffer = File.ReadAllBytes(file);
        }
        catch (System.Exception exception)
        {
            UnityEngine.Debug.LogError(exception.Message);
            return string.Empty;
        }
        if (buffer.Length > 0)
        {
            for (uint i = 0; i < buffer.Length; i++)
            {
                if (buffer[i] == 0)
                {
                    buffer[i] = 1;
                }
            }
            string str = Encoding.ASCII.GetString(buffer);
            int index = str.IndexOf(libraryDefinition);
            if (index == -1)
            {
                return string.Empty;
            }
            string str2 = str.Substring(index + libraryDefinition.Length, 20);
            int num3 = 0;
            for (int j = 0; j < str2.Length; j++)
            {
                if (str2[j] == ' ')
                {
                    num3++;
                }
            }
            if (num3 < 3)
            {
                UnityEngine.Debug.LogError(string.Format("Error while parsing OS version, was looking for '{0}' in file '{1}'", libraryDefinition, file));
                return string.Empty;
            }
            return str2;
        }
        UnityEngine.Debug.LogError(string.Format("Failed to find {0} file\n", file));
        return string.Empty;
    }

    internal static string GetPlayerSubDir(WiiBuildSubtarget subTarget)
    {
        switch (subTarget)
        {
            case WiiBuildSubtarget.DVD:
                return "unity-disk";

            case WiiBuildSubtarget.WiiWare:
                return "unity-wiiware";

            case WiiBuildSubtarget.DVDLibrary:
                return "unity-disk-lib";

            case WiiBuildSubtarget.WiiWareLibrary:
                return "unity-wiiware-lib";
        }
        return string.Empty;
    }

    internal static string GetStrapReminderSubDir(WiiRegion region)
    {
        switch (region)
        {
            case WiiRegion.Japan:
                return "/DVD/Strap/jp";

            case WiiRegion.USA:
                return "/DVD/Strap/us";

            case WiiRegion.Europe:
                return "/DVD/Strap/eu";

            case WiiRegion.China:
                return "/DVD/Strap/cn";

            case WiiRegion.Korea:
                return "/DVD/Strap/kr";

            case WiiRegion.Taiwan:
                return "/DVD/Strap/tw";
        }
        UnityEngine.Debug.LogError("Unknown region: " + region.ToString());
        return "/DVD/Strap/eu";
    }

    internal static bool IsDVDBuild()
    {
        WiiBuildSubtarget wiiBuildSubtarget = EditorUserBuildSettings.wiiBuildSubtarget;
        return ((wiiBuildSubtarget == WiiBuildSubtarget.DVD) || (wiiBuildSubtarget == WiiBuildSubtarget.DVDLibrary));
    }

    internal static bool IsLibraryBuild()
    {
        WiiBuildSubtarget wiiBuildSubtarget = EditorUserBuildSettings.wiiBuildSubtarget;
        return ((wiiBuildSubtarget == WiiBuildSubtarget.DVDLibrary) || (wiiBuildSubtarget == WiiBuildSubtarget.WiiWareLibrary));
    }

    private static string MakeRelative(string filepath, string rootpath)
    {
        if (!filepath.StartsWith(rootpath) || (filepath.Length < rootpath.Length))
        {
            return filepath;
        }
        string str = filepath.Substring(rootpath.Length);
        if ((str.Length <= 0) || ((str[0] != '/') && (str[0] != Path.DirectorySeparatorChar)))
        {
            return str;
        }
        return str.Substring(1);
    }

    internal static void PostProcess(BuildTarget target, BuildOptions options, string installPath, string stagingAreaData, string stagingArea, string productName, string playerPackage)
    {
        wiiBuildTools = BuildPipeline.GetBuildToolsDirectory(BuildTarget.Wii);
        moduleName = (EditorUserBuildSettings.wiiBuildSubtarget != WiiBuildSubtarget.WiiWareLibrary) ? "UnityWii" : "UnityWiiWare";
        moduleExtension = !IsLibraryBuild() ? ".elf" : ".a";
        moduleNameExt = moduleName + moduleExtension;
        isDevelopmentBuild = (options & BuildOptions.Development) != BuildOptions.None;
        if (!IsLibraryBuild())
        {
            bool flag = EditorUserBuildSettings.wiiBuildDebugLevel != WiiBuildDebugLevel.None;
            if (isDevelopmentBuild != flag)
            {
                UnityEngine.Debug.LogError(string.Format("BuildOptions are inconsistent with EditorUserBuildSettings.wiiDebugLevel, BuildOptions ({0}) and wiiDebugLevel ({1})", !isDevelopmentBuild ? "NonDevelopment" : "Development", EditorUserBuildSettings.wiiBuildDebugLevel.ToString()));
                return;
            }
        }
        if (!IsLibraryBuild() || ValidateSDKVersion(playerPackage + "/unity-disk/unity-disk.release.elf"))
        {
            if (IsDVDBuild())
            {
                string[] strArray = new string[] { "/CWAutomation.exe", "/hio2.dll", "/Hio2Wrapper.dll" };
                if (IsLibraryBuild())
                {
                    FileUtil.CopyFileOrDirectory(playerPackage + "/WiiLibrary/Common", stagingArea + "/Libs");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/main.cpp", stagingArea + "/main.cpp");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/Unity.cpp", stagingArea + "/Unity.cpp");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/Unity.h", stagingArea + "/Unity.h");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/UnityWiiDVD.mcp", stagingArea + "/UnityWiiDVD.mcp");
                    string str = "/" + GetPlayerSubDir(EditorUserBuildSettings.wiiBuildSubtarget);
                    string[] strArray2 = new string[] { "release", "master" };
                    foreach (string str2 in strArray2)
                    {
                        FileUtil.ReplaceFile(playerPackage + str + "/ProphecySDK." + str2 + ".a", stagingArea + "/Libs");
                        FileUtil.ReplaceFile(playerPackage + str + "/rvlaux-wii." + str2 + ".a", stagingArea + "/Libs");
                        string[] textArray5 = new string[] { playerPackage, str, "/", str, ".", str2, moduleExtension };
                        string[] textArray6 = new string[] { stagingArea, "/Libs/", moduleName, ".", str2, moduleExtension };
                        if (!CopyAndModifyUnityFile(string.Concat(textArray5), string.Concat(textArray6), productName, str2))
                        {
                            return;
                        }
                    }
                }
                else
                {
                    string str3 = string.Format("/{0}/{0}.", GetPlayerSubDir(EditorUserBuildSettings.wiiBuildSubtarget));
                    if (isDevelopmentBuild)
                    {
                        foreach (string str4 in strArray)
                        {
                            FileUtil.CopyFileOrDirectory(playerPackage + "/Common" + str4, stagingArea + str4);
                        }
                    }
                    string[] strArray5 = new string[] { "debug", "release", "master" };
                    string variantName = strArray5[(int) EditorUserBuildSettings.wiiBuildDebugLevel];
                    FileUtil.CopyFileOrDirectory(playerPackage + str3 + variantName + ".map", stagingArea + "/" + moduleName + ".map");
                    if (!CopyAndModifyUnityFile(playerPackage + str3 + variantName + moduleExtension, stagingArea + "/" + moduleNameExt, productName, variantName))
                    {
                        return;
                    }
                }
                Directory.CreateDirectory(stagingArea + "/Data/Strap");
                foreach (string str7 in Directory.GetFiles(playerPackage + GetStrapReminderSubDir(PlayerSettings.Wii.region), "*.tpl", SearchOption.TopDirectoryOnly))
                {
                    File.Copy(str7, stagingArea + "/Data/Strap/" + Path.GetFileName(str7));
                }
                FileUtil.CopyFileOrDirectory(playerPackage + "/DVD/run.cmd", stagingArea + "/run.cmd");
                FileUtil.CopyFileOrDirectory(playerPackage + "/DVD/stop.cmd", stagingArea + "/stop.cmd");
                FileUtil.CopyFileOrDirectory(playerPackage + "/Data/Resources", stagingArea + "/Data/Resources");
                FileUtil.CopyFileOrDirectory(playerPackage + "/DVD/hbm/HomeButton2", stagingArea + "/Data/HomeButton2");
                CreateDirectoryStructure(installPath);
                FileUtil.MoveFileOrDirectory(stagingArea + "/Data", installPath + "/Package/Data");
                if (IsLibraryBuild())
                {
                    FileUtil.CopyFileOrDirectory(stagingArea + "/Libs", installPath + "/Source/Libs");
                    ReplaceFileIfMissing(stagingArea + "/main.cpp", installPath + "/Source/main.cpp");
                    ReplaceFileIfMissing(stagingArea + "/Unity.cpp", installPath + "/Source/Unity.cpp");
                    ReplaceFileIfMissing(stagingArea + "/Unity.h", installPath + "/Source/Unity.h");
                    ReplaceFileIfMissing(stagingArea + "/UnityWiiDVD.mcp", installPath + "/UnityWiiDVD.mcp");
                }
                else
                {
                    if (isDevelopmentBuild)
                    {
                        foreach (string str8 in strArray)
                        {
                            FileUtil.ReplaceFile(stagingArea + str8, installPath + "/CWAutomation" + str8);
                        }
                    }
                    FileUtil.ReplaceFile(stagingArea + "/" + moduleName + ".map", installPath + "/Package/" + moduleName + ".map");
                    Process.Start(wiiBuildTools + "/MiniMapBuilder.exe", string.Format("\"{0}/{2}.map\" \"{1}/Package/{2}.minimap\"", stagingArea, installPath, moduleName));
                    FileUtil.ReplaceFile(stagingArea + "/" + moduleNameExt, installPath + "/Package/WiiPlayer/" + moduleNameExt);
                }
                FileUtil.ReplaceFile(stagingArea + "/run.cmd", installPath + "/run.cmd");
                FileUtil.ReplaceFile(stagingArea + "/stop.cmd", installPath + "/stop.cmd");
                File.WriteAllText(installPath + "/" + moduleName + ".ddf", GenerateDdfContent(installPath + "/Package/Data", productName, moduleName));
            }
            else
            {
                if (IsLibraryBuild())
                {
                    FileUtil.CopyFileOrDirectory(playerPackage + "/WiiLibrary/Common", stagingArea + "/Libs");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/main.cpp", stagingArea + "/main.cpp");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/Unity.cpp", stagingArea + "/Unity.cpp");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/Unity.h", stagingArea + "/Unity.h");
                    FileUtil.ReplaceFile(playerPackage + "/WiiLibrary/UnityWiiWare.mcp", stagingArea + "/UnityWiiWare.mcp");
                    string str9 = "/" + GetPlayerSubDir(EditorUserBuildSettings.wiiBuildSubtarget);
                    string[] strArray8 = new string[] { "release", "master" };
                    foreach (string str10 in strArray8)
                    {
                        FileUtil.ReplaceFile(playerPackage + str9 + "/ProphecySDK." + str10 + ".a", stagingArea + "/Libs");
                        FileUtil.ReplaceFile(playerPackage + str9 + "/rvlaux-wiiware." + str10 + ".a", stagingArea + "/Libs");
                        string[] textArray11 = new string[] { playerPackage, str9, "/", str9, ".", str10, moduleExtension };
                        string[] textArray12 = new string[] { stagingArea, "/Libs/", moduleName, ".", str10, moduleExtension };
                        if (!CopyAndModifyUnityFile(string.Concat(textArray11), string.Concat(textArray12), productName, str10))
                        {
                            return;
                        }
                    }
                }
                else
                {
                    string str11 = string.Format("/{0}/{0}.", GetPlayerSubDir(EditorUserBuildSettings.wiiBuildSubtarget));
                    string[] strArray10 = new string[] { "debug", "release", "master" };
                    string str12 = strArray10[(int) EditorUserBuildSettings.wiiBuildDebugLevel];
                    if (!CopyAndModifyUnityFile(playerPackage + str11 + str12 + ".elf", stagingArea + "/" + moduleNameExt, productName, str12))
                    {
                        return;
                    }
                    FileUtil.CopyFileOrDirectory(playerPackage + str11 + str12 + ".map", stagingArea + "/" + moduleName + ".map");
                }
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/runNMenu.cmd", stagingArea + "/runNMenu.cmd");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/runWad.cmd", stagingArea + "/runWad.cmd");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/stop.cmd", stagingArea + "/stop.cmd");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/WadBuilderCS.exe", stagingArea + "/WadBuilderCS.exe");
                FileUtil.CopyFileOrDirectory(playerPackage + "/Data/Resources", stagingArea + "/Data/Resources");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/hbm/shared", stagingArea + "/shared");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/Strap/StrapImage.arc", stagingArea + "/shared/StrapImage.arc");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/Viewer", stagingArea + "/Viewer");
                Directory.CreateDirectory(stagingArea + "/Data/hbm");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/hbm/network.csv", stagingArea + "/Data/hbm/network.csv");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/hbm/home.csv", stagingArea + "/Data/hbm/home.csv");
                FileUtil.CopyFileOrDirectory(playerPackage + "/WiiWare/hbm/HomeButtonSe.arc", stagingArea + "/Data/hbm/HomeButtonSe.arc");
                switch (PlayerSettings.Wii.region)
                {
                    case WiiRegion.Japan:
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageJpn.tpl");
                        break;

                    case WiiRegion.USA:
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageEng.tpl");
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageSpa.tpl");
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageFra.tpl");
                        break;

                    case WiiRegion.Europe:
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageEng.tpl");
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageSpa.tpl");
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageIta.tpl");
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageNed.tpl");
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageFra.tpl");
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageGer.tpl");
                        break;

                    case WiiRegion.China:
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageChn.tpl");
                        break;

                    case WiiRegion.Korea:
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageKor.tpl");
                        break;

                    case WiiRegion.Taiwan:
                        File.Copy(playerPackage + "/WiiWare/hbm/manualPage.tpl", stagingArea + "/Data/hbm/manualPageChn.tpl");
                        break;

                    default:
                        UnityEngine.Debug.LogError("Unknown region: " + PlayerSettings.Wii.region.ToString());
                        break;
                }
                CreateDirectoryStructure(installPath);
                FileUtil.ReplaceFile(stagingArea + "/runNMenu.cmd", installPath + "/runNMenu.cmd");
                FileUtil.ReplaceFile(stagingArea + "/runWad.cmd", installPath + "/runWad.cmd");
                FileUtil.ReplaceFile(stagingArea + "/stop.cmd", installPath + "/stop.cmd");
                FileUtil.ReplaceFile(stagingArea + "/WadBuilderCS.exe", installPath + "/WadBuilderCS.exe");
                WriteWADSettings(installPath + "/wadSettings.xml");
                FileUtil.MoveFileOrDirectory(stagingArea + "/Viewer", installPath + "/Package/Viewer");
                FileUtil.MoveFileOrDirectory(stagingArea + "/Shared", installPath + "/Package/Shared");
                FileUtil.MoveFileOrDirectory(stagingArea + "/Data", installPath + "/Package/Data");
                if (IsLibraryBuild())
                {
                    FileUtil.CopyFileOrDirectory(stagingArea + "/Libs", installPath + "/Source/Libs");
                    ReplaceFileIfMissing(stagingArea + "/main.cpp", installPath + "/Source/main.cpp");
                    ReplaceFileIfMissing(stagingArea + "/Unity.cpp", installPath + "/Source/Unity.cpp");
                    ReplaceFileIfMissing(stagingArea + "/Unity.h", installPath + "/Source/Unity.h");
                    ReplaceFileIfMissing(stagingArea + "/UnityWiiWare.mcp", installPath + "/UnityWiiWare.mcp");
                }
                else
                {
                    FileUtil.ReplaceFile(stagingArea + "/" + moduleName + ".map", installPath + "/Package/" + moduleName + ".map");
                    Process.Start(wiiBuildTools + "/MiniMapBuilder.exe", string.Format("\"{0}/{2}.map\" \"{1}/Package/Data/{2}.minimap\"", stagingArea, installPath, moduleName));
                    FileUtil.ReplaceFile(stagingArea + "/" + moduleNameExt, installPath + "/Package/WiiWarePlayer/" + moduleNameExt);
                }
            }
            if (IsLibraryBuild())
            {
                ReplaceFileIfMissing(wiiBuildTools + "/MiniMapBuilder.exe", installPath + "/MiniMapBuilder.exe");
                StringBuilder builder = new StringBuilder();
                builder.AppendLine("%NDEV%\\bin\\setndenv.exe DvdRoot \"%~dp0Package\"");
                if (IsDVDBuild())
                {
                    builder.AppendLine(@"MiniMapBuilder.exe Package\WiiPlayer\UnityWii.map Package\UnityWii.minimap");
                }
                else
                {
                    builder.AppendLine(@"MiniMapBuilder.exe Package\WiiWarePlayer\Unity.map Package\UnityWii.minimap");
                    builder.AppendLine("WadBuilderCS.exe");
                }
                File.WriteAllText(installPath + "/PostLinker.bat", builder.ToString());
                if (!IsDVDBuild())
                {
                    StringBuilder builder2 = new StringBuilder();
                    builder2.AppendLine("@echo off");
                    builder2.AppendLine("echo Run this if you want to load UnityWiiWare.mcp");
                    builder2.AppendLine("echo When project is loaded, go Debugger->RemoteDebugging->EditConnection");
                    builder2.AppendLine("echo In Load Script field enter wadrun.bat UnityWii.wad");
                    builder2.AppendLine("echo Don't forget to restore this field to 'ndrun.bat $F $P' when you switch to DVD title debugging");
                    builder2.AppendLine("pause");
                    builder2.AppendLine("@echo on");
                    builder2.AppendLine(@"SET PATH=%PATH%;%REVOLUTION_SDK_ROOT%\x86\bin\");
                    builder2.AppendLine("UnityWiiWare.mcp");
                    File.WriteAllText(installPath + "/SetupEnvVarsLoadProject.cmd", builder2.ToString());
                }
            }
            if (Directory.Exists("Assets/StreamingAssets"))
            {
                FileUtil.CopyDirectoryRecursiveForPostprocess("Assets/StreamingAssets", installPath + "/Package/Data/StreamingAssets", true);
            }
        }
    }

    internal static void ReplaceFileIfMissing(string srcPath, string dstPath)
    {
        if (!File.Exists(dstPath))
        {
            FileUtil.ReplaceFile(srcPath, dstPath);
        }
    }

    internal static int ReplaceString(byte[] srcData, int location, string replace, int replaceMax)
    {
        if (location <= 0)
        {
            return -1;
        }
        byte[] bytes = Encoding.ASCII.GetBytes(replace);
        int num = Math.Min(bytes.Length, replaceMax);
        for (int i = 0; i < num; i++)
        {
            srcData[location + i] = bytes[i];
        }
        srcData[location + num] = 0;
        return location;
    }

    private static short SwapInt16(short v)
    {
        return (short) (((v & 0xff) << 8) | ((v >> 8) & 0xff));
    }

    private static int SwapInt32(int v)
    {
        return (((SwapInt16((short) v) & 0xffff) << 0x10) | (SwapInt16((short) (v >> 0x10)) & 0xffff));
    }

    internal static bool ValidateSDKVersion(string elfFilePath)
    {
        string oSVersionFromFile = GetOSVersionFromFile(elfFilePath, "RVL_SDK - OS \trelease build:");
        if (oSVersionFromFile == string.Empty)
        {
            UnityEngine.Debug.LogError("Couldn't locate RVL_SDK version inside " + elfFilePath);
            return false;
        }
        string environmentVariable = Environment.GetEnvironmentVariable("REVOLUTION_SDK_ROOT");
        if (environmentVariable == null)
        {
            UnityEngine.Debug.LogError("Enviroment variable REVOLUTION_SDK_ROOT is not set!");
            return false;
        }
        char[] trimChars = new char[] { '\\' };
        string file = environmentVariable.TrimEnd(trimChars) + @"\RVL\lib\os.a";
        string strB = GetOSVersionFromFile(file, "RVL_SDK - OS \trelease build:");
        if (strB == string.Empty)
        {
            UnityEngine.Debug.LogError("Couldn't locate RVL_SDK version inside " + file);
            return false;
        }
        if (string.Compare(oSVersionFromFile, strB, true) != 0)
        {
            UnityEngine.Debug.LogError(string.Format("Your RVL_SDK version is incorrect, expected '{0}', but found '{1}'", oSVersionFromFile, strB));
            return false;
        }
        return true;
    }

    private static void WriteWADSettings(string path)
    {
        StringBuilder builder = new StringBuilder();
        builder.AppendLine("<WadSettings>");
        builder.AppendLine(string.Format("\t<GameCode>\"{0}\"</GameCode>", PlayerSettings.Wii.gameCode));
        builder.AppendLine(string.Format("\t<CompanyCode>\"{0}\"</CompanyCode>", PlayerSettings.Wii.companyCode));
        builder.AppendLine(string.Format("\t<Version>\"{0}\"</Version>", PlayerSettings.Wii.gameVersion));
        switch (EditorUserBuildSettings.wiiBuildSubtarget)
        {
            case WiiBuildSubtarget.WiiWare:
                builder.AppendLine("\t<ElfName>Package\\WiiWarePlayer\\UnityWii.elf</ElfName>");
                break;

            case WiiBuildSubtarget.WiiWareLibrary:
                builder.AppendLine("\t<ElfName>Package\\WiiWarePlayer\\Unity.elf</ElfName>");
                break;

            default:
                UnityEngine.Debug.LogError("Unknown wii target for building wad settings");
                break;
        }
        builder.AppendLine("\t<CompressFiles>");
        string[] strArray = new string[] { "*.dll", "*.exe" };
        foreach (string str in strArray)
        {
            builder.AppendLine(string.Format("\t\t<Extension value=\"{0}\" directory=\"{1}\" includeSubdirs=\"{2}\" />", str, "Package/Data/", "True"));
        }
        builder.AppendLine("\t</CompressFiles>");
        builder.AppendLine("</WadSettings>");
        File.WriteAllText(path, builder.ToString());
    }

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    private struct PlayerData
    {
        public byte region;
        public byte hbmConfirmMessage;
        public int movieMemKB;
        public byte mixed;
        public byte controllerCount;
        public int memorySetup0;
        public int memorySetup1;
        public int memorySetup2;
        public int memorySetup3;
    }
}

